package Java8新特性;

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/*
     Java8中有两大最为重要的改变,第一个是 Lambda 表达式,另外一个则是 Stream API
     Stream API (java.util.stream)把真正的函数式编程风格引入到Java中,这是目前为止对Java类库最好的补充,因为Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码
     Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作,使用 Stream API对集合数据进行操作,就类似于使用 SQL 执行的数据库查询,也可以使用 Stream API 来并行执行操作,简言之,Stream API 提供了一种高效且易于使用的处理数据的方式

    为什么要使用Stream API
         实际开发中,项目中多数数据源都来自于Mysql,Oracle等,这些数据库可以直接进行数据的处理,但现在数据源可以更多了,有MongoDB、Redis等,而这些NoSQL的数据就需要 Java层面去处理
         Stream 和 Collection 集合的区别:Collection 是一种静态的内存数据结构,而 Stream 是有关计算的,前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算

    Stream实质:数据渠道,用于操作数据源(集合、数组等)所生成的元素序列,"集合讲的是数据,Stream讲的是计算！"
    注意
         Stream 自己不会存储元素
         Stream 不会改变源对象,相反,它们会返回一个持有结果的新Stream
         Stream 操作是延迟执行的,这意味着他们会等到需要结果的时候才执行

    Stream 的操作三个步骤
         1- 创建 Stream
            一个数据源(如:集合、数组),获取一个流
         2- 中间操作
            一个中间操作链,对数据源的数据进行处理
         3- 终止操作(终端操作)
            一旦执行终止操作,就执行中间操作链,并产生结果,之后,不会再被使用 --> 只有执行终止操作时,才会执行中间操作链,这就是延迟执行

    创建 Stream方式一:通过集合
        Java8 中的 Collection 接口被扩展,提供了两个获取流的方法:
              default Stream<E> stream():返回一个顺序流
              default Stream<E> parallelStream():返回一个并行流

    创建 Stream方式二:通过数组
        Java8 中的 Arrays 的静态方法 stream() 可以获取数组流:
              static <T> Stream<T> stream(T[] array):返回一个流
                 重载形式,能够处理对应基本类型的数组:
                      public static IntStream stream(int[] array)
                      public static LongStream stream(long[] array)
                      public static DoubleStream stream(double[] array)

    创建 Stream方式三:通过Stream的of()
        可以调用Stream类静态方法 of(),通过显示值创建一个流,它可以接收任意数量的参数
              public static<T> Stream<T> of(T... values):返回一个流

    创建 Stream方式四:创建无限流
             可以使用静态方法 Stream.iterate() 和 Stream.generate()创建无限流
            迭代
                public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
            生成
                public static<T> Stream<T> generate(Supplier<T> s)
 */
public class StreamAPI05 {

    //创建 Stream 方式一:通过集合
    @Test
    public void test1(){
        List<Employee> list = EmployeeData.getEmployees();

        //返回一个顺序流
        Stream<Employee> stream1 = list.stream();

        //返回一个并行流
        Stream<Employee> stream2 = list.parallelStream();
    }

    //创建 Stream方式二:通过数组
    @Test
    public void test2(){
        int[] arr = {1,2,3,4,5,6};

        //Arrays 的静态方法 stream() 可以获取数组流
        IntStream stream1 = Arrays.stream(arr);

        Employee e1 = new Employee(1001,"Tom");
        Employee e2 = new Employee(1002,"Jerry");
        Employee[] eList = {e1,e2};
        //Arrays 的静态方法 stream() 可以获取数组流
        Stream<Employee> stream2 = Arrays.stream(eList);  //类型通过Stream的泛型体现
    }

    //创建 Stream方式三:通过Stream的of()
    @Test
    public void test3(){
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4,5);
    }

    //创建 Stream方式四:创建无限流  --> 适用于批量造数据
    @Test
    public void test4(){

        //迭代  遍历前10个偶数
        Stream.iterate(0, t -> t+2).limit(10).forEach(System.out::println);

        //生成
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }
}
